<?php

/**
 * 中远国际 SDK
 * @author chenyun
 * 
 */

namespace App\Service\VendorClient\Shopzhongyuan;
use App\Service\Code\Normal;
use App\Service\TaskServer\TaskWorker;
use Service\AppService\IdService;
use function GuzzleHttp\json_encode;

class ShopzhongyuanApiClient
{
    private $account  = 'shopzhongyuan';
    protected $config;
    protected $RouteMap = [
        'createOrder'   => '/msd_gyWMS/gatewayNew',
        'cancelOrder'   => '/msd_gyWMS/gateway',
    ];
 
    /**
     * 初始参数
     * @param obj $collection
     */
    public function __construct( $apiBody = [] ) 
    {
        $this->config = $apiBody;
    }
    
    /**
     * 创建订单
     */
    public function createOrder( $params = [] ) 
    {   
        ini_set('serialize_precision', 16);
        
        if( empty($params['supplierOrder']) || empty($params['orderGoods']) || empty($params['order']) || empty($params['binfo']) ) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder or orderGoods or order or binfo");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        $order     = $params['order'];
        $binfo     = $params['binfo'];
        $supplier_skuid_map = $params['supplier_skuid_map'];
        
        //运费
        $deliver_money  = $orderInfo['deliver_money'];
        //商品下单组
        $order_item_list = [];
        $productAmt  =$n_kos   = $TaxAmt = 0 ;
        foreach ($params['orderGoods'] as $key => $item )
        {
            //卖价
            $price              = $item['price'];
            //商品购买规格数量
            $spec_num           = $item['spec_num'];
            //商品购买数量(下单数量 X 起售数量)
            $quantity           = $item['quantity'];
            //实际购买数量
            $buyAcount          = $spec_num * $quantity ;
            //如果商品除不尽，得多取以为，减去实际金额为折扣，折扣不能为负数
            if( $key == 0 ) {
                $singleDeliveryMoney = bcdiv((string)$deliver_money,(string)$quantity,3);
                $singleDeliveryMoney = bcmul((string)$singleDeliveryMoney,(string)100,1);
                $singleDeliveryMoney = bcdiv((string)ceil($singleDeliveryMoney), (string)100,2);
                $price               = bcadd((string)$price, (string)$singleDeliveryMoney,2);
            }
            //单个商品价格
            $singleGoodsPrice   = bcdiv((string)$price, (string)$spec_num,3);
            $singleGoodsPrice   = ceil(bcmul((string)$singleGoodsPrice,(string)'100',1));
            $singleGoodsPrice   = bcdiv((string)$singleGoodsPrice,'100',2);
            $totalGoods         = bcmul((string)$singleGoodsPrice,(string)$buyAcount,2);

            //含税税率
            $tax_rate           = bcadd('1', (string)$item['tax_rate'],4);
            
            //不含税价格
            $not_tax_price      = bcdiv((string)$singleGoodsPrice, (string)$tax_rate,3);
            // echo "含税税率:".$tax_rate."不含税价格：".$not_tax_price;
            $not_tax_price      = ceil(bcmul((string)$not_tax_price,(string)'100',1));
            // echo "含税税率:".$tax_rate."不含税价格：".$not_tax_price;
            $not_tax_price      = bcdiv((string)$not_tax_price,'100',2);
            
            //税金
            $singleGoodsTax     = bcsub((string)$singleGoodsPrice, (string)$not_tax_price,3);
            
            //单个商品总税金
            $totalGoodsTax  = bcmul((string)$singleGoodsTax,(string)$buyAcount,2);
            
            //单个商品总不含税价格
            $totalGoods     = bcmul((string)$not_tax_price,(string)$buyAcount,2);
            //商品组
            if(empty($supplier_skuid_map[$item['supplier_skuid']])){

                return Normal::returnCode(Normal::FAIL,"供应商商品ID".$item['supplier_skuid']."数据不存在，请核实！");
            }
            $orderItemXml[]= [
                'order_item_id'     => $supplier_skuid_map[$item['supplier_skuid']],
                'gnum'              => ($key+1),
                'goodsreportno'     => $item['supplier_skucode'],
                'item_id'           => $item['supplier_skucode'],
                'item_name'         => $item['goods_name'],
                'item_code'         => $supplier_skuid_map[$item['supplier_skuid']],
                'inventory_type'    => "1",
                'item_quantity'     => $buyAcount,
                'item_price'        => bcmul((string)$not_tax_price,'100'),
                'item_version'      => "1",
                'cus_code'          => $this->config['cus_code'],
                'sku_code'          => $item['supplier_skucode'],
                'item_spec'         => "NA",
                'origin_country'    => "NA",
                'hscode'            => "NA",
                'itemLink'          => "NA",
            ];
            $n_kos = bcadd((string)$n_kos,(string)$item["weight"],2);
            $productAmt = bcadd((string)$productAmt,(string)$totalGoods,2);
            $TaxAmt = bcadd((string)$TaxAmt,(string)$totalGoodsTax,2);
        }
        //实际下单金额
        $real_total_money = $orderInfo['real_total_money'];
        //订单总金额 = 含税商品总金额 + 运费 - 优惠金额
        $ActualPaidAmt = bcadd((string)$productAmt,(string)$TaxAmt,2);
        //优惠金额
        $discount_money = bcsub((string)$ActualPaidAmt,$real_total_money,2);
        //下单支付的时候支付信息
        $apply_extends  = @json_decode($orderInfo['apply_extends'],true);
        
        //支付时间
        $payTime        = empty($order['payTime']) ? $orderInfo['pay_time'] :$order['payTime'];
        //支付时间
        $pay_time       = $payTime ? $payTime : time();
        $pay_time       = date('Y-m-d H:i:s',$pay_time);
        
        //支付流水号
        $pay_sn         = $order['paySerial']??$orderInfo['pay_sn'];

        //电商平台信息
        $enterpriseNum = $apply_extends['enterpriseNum'] ?? '';
        $enterpriseName = $apply_extends['enterpriseName'] ?? '';
        $enterpriseNum = $order['enterpriseNum'] ? $order['enterpriseNum'] : $enterpriseNum;
        $enterpriseName = $order['enterpriseName'] ? $order['enterpriseName'] : $enterpriseName;

        //支付公司信息
        $payCommanyCode = $apply_extends['payCommanyCode'] ?? '';
        $payCommanyName = $apply_extends['payCommanyName'] ?? '';
        $payCommanyCode = $order['payCommanyCode'] ? $order['payCommanyCode'] : $payCommanyCode;
        $payCommanyName = $order['payCommanyName'] ? $order['payCommanyName'] : $payCommanyName;
        
        //收货人信息拼接格式：邮箱^^^省^^^市^^^区^^^详细地址^^^收货人^^^收货电话^^^收货手机，没有的值传NA
        $receiver_info="NA^^^".$orderInfo['province']."^^^".$orderInfo['city']."^^^".$orderInfo['district']."^^^".$orderInfo['receive_address']."^^^".$orderInfo['receive_name']."^^^".$orderInfo['recveive_phone']."^^^".$orderInfo['recveive_phone'];
        //创建订单数据
        $content = [
            "store_code"        => $this->config["store_code"],
            "order_code"        => $orderInfo['supplier_dsn'],
            "order_type"        => $this->config["order_type"],
            "order_source"      => $this->config["order_source"],
            "order_create_time" => date("Y-m-d H:i:s",time()),
            "v_ieflag"          => "I",
            "v_card_type"       => "01",
            "v_transport_code"  => "NA",
            "v_package_typecode"=> "NA",
            "v_qy_state"        => "NA",
            "n_kos"             => $n_kos,
            "v_traf_name"       => "NA",
            "discount"          => $discount_money,
            "receiver_info"     => $receiver_info,
            "sender_info"       => $receiver_info,
            "order_item_list"   => $orderItemXml,
            "package_count"     => 1,
            "order_ename"       => $orderInfo["buyer_realname"],
            "order_phone"       => $orderInfo["buyer_phone"],
            "order_cardno"      => $orderInfo["buyer_idcard"],
            "remark"            => $orderInfo["order_remark"],
            "freight"           => $orderInfo["deliver_money"],
            "Insurance"         => "0.00",
            "tax"               => $TaxAmt,
            "paycompany"        => $payCommanyName,
            "payserialno"       => $pay_sn,
            "payCode"           => $payCommanyCode,
            "initalRequest"     => (!empty($orderInfo["apply_request"]) ? $orderInfo["apply_request"] : "NA"),
            "initalResponse"    => (!empty($orderInfo["apply_request"]) ? $orderInfo["apply_request"] : "NA"),
            "totalAmount"       => $real_total_money,
            "verDept"           => "NA",
            "payType"           => "NA",
            "tradingTime"       => $pay_time,
            "recpAccount"       => "NA",
            "recpName"          => "NA",
            "currency"          => "142",
            "tms_service_code"  => $this->config["tms_service_code"],
        ];
        $sign = $this->getSign($content);
        $data = [
            "sign_type"     => "MD5",
            "notify_type"   => "COSCO_STOCK_OUT_ORDER",
            "input_charset" => "UTF-8",
            "sign"          => $sign,
            "content"       => json_encode($content,JSON_UNESCAPED_UNICODE),
        ];
        $requestParam = [
            'method'    => 'createOrder',
            'data'      => $data,
        ];
        return $this->execute($requestParam);
    }
   
    /**
     * 获取取消订单
     */
    public function cancelOrder( $params = [] ) 
    {
         if( empty($params['supplierOrder'])) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder ");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        $order     = $params['order'];
        $content=$this->arrToXml([
            'request' =>$this->arrToXml([
                'orderCode'     => $orderInfo['supplier_dsn'],
                'orderType'     => $this->config['order_type'],
                'orderSource'   => $this->config['order_source']
            ])
        ]);
        
        $content='<?xml version="1.0" encoding="utf-8"?>'.$content;
        $sign = $this->getCancelSign($content);
        $data = [
            "sign_type"     => "MD5",
            "notify_type"   => "COSCO_STOCK_CANCEL_ORDER",
            "input_charset" => "UTF-8",
            "sign"          => $sign,
            "content"       => $content,
        ];
        $requestParam = [
            'method'    => 'cancelOrder',
            'data'      => $data
        ];
        return $this->cancelExecute($requestParam);
    }
    
    /**
     * 组装xml
     */
    public function arrToXml(  $params = [] )
    {
        $xml = '';
        foreach ($params as $key=>$val){
            $xml .= "<{$key}>{$val}</{$key}>";
        }
        return $xml;
    }
    /**
     * 加签
     * @param array $param
     */
    protected function getSign ($param)
    {
        $param=json_encode($param,JSON_UNESCAPED_UNICODE);
        $string=base64_encode(md5($param.$this->config["key"]));
        return $string;
    }
    
    /**
     * 加签
     * @param array $param
     */
    protected function getCancelSign ($param)
    {
        $string=base64_encode(md5($param.$this->config["key"]));
        return $string;
    }
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function execute( $param = [] )  
    {
        if(empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }
        $method = $param['method'];
        $url = $this->config['baseurl'].$this->RouteMap[$method];
        $parameter = [
            [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $url,
                'data'      => $param['data'],
                'method'    => 'post',
                'format'    => 'x-www-form-urlencoded',
                'header'    => [],
            ],
        ];
        $resTask = TaskWorker::instance()->addTask($parameter);
        $resTask = current($resTask);
        $res     = $resTask['response']['result'];
        $resHttp = @json_decode($res,true);
        if(isset($resHttp['success']) && $resHttp['success'] == "true" ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$resHttp);
        }
        $message = isset($resHttp['errorMsg']) ? $resHttp['errorMsg'] : '请求失败';
        return Normal::returnCode(Normal::FAIL,$message);
    }
    
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function cancelExecute( $param = [] )
    {
        if(empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }
        $method = $param['method'];
        $url = $this->config['baseurl'].$this->RouteMap[$method];
        $parameter = [
            [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $url,
                'data'      => $param['data'],
                'method'    => 'post',
                'format'    => 'x-www-form-urlencoded',
                'header'    => [],
            ],
        ];
        $resTask = TaskWorker::instance()->addTask($parameter);
        $resTask = current($resTask);
        $res     = $resTask['response']['result'];
        $xmlObj  = simplexml_load_string($res,"SimpleXMLElement", LIBXML_NOCDATA);
        $jsonStr = json_encode($xmlObj);
        $resHttp = @json_decode($jsonStr, true);
        if(isset($resHttp['success']) && $resHttp['success'] == "true" ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$resHttp);
        }
        $message = isset($resHttp['errorMsg']) ? $resHttp['errorMsg'] : '请求失败';
        return Normal::returnCode(Normal::FAIL,$message);
    }
}